package com.wkbb.sports.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.wkbb.common.constants.RedisKeyConstant;
import com.wkbb.common.dto.basic.DistrictDto;
import com.wkbb.common.redis.RedisTemplateUtil;
import com.wkbb.sports.dto.*;
import com.wkbb.sports.mapper.StatisticsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.basic.EmployeeInfoDto;
import com.wkbb.sports.feign.BasicFeignService;
import com.wkbb.sports.mapper.HlifeTrainMapper;
import com.wkbb.sports.mapper.HlifeTrainStudentMapper;
import com.wkbb.sports.model.HlifeTrain;
import com.wkbb.sports.model.HlifeTrainStudent;
import com.wkbb.sports.service.StatisticsService;
import com.wkbb.sports.utils.DateUtil;
import com.wkbb.sports.utils.Statistics;
import com.wkbb.sports.utils.StatisticsAvgScore;
import com.wkbb.sports.utils.StatisticsStudent;
import com.wkbb.sports.utils.WeekUtil;

import lombok.extern.slf4j.Slf4j;


@Service
@Slf4j
public class StatisticsServiceImpl implements StatisticsService {
	
	@Autowired
	private StatisticsMapper statisticsMapper;
	@Autowired
	private HlifeTrainMapper trainMapper;
	
	@Autowired
	private HlifeTrainStudentMapper trainStudentMapper;

	@Autowired
	private BasicFeignService basicFeignService;

	@Autowired
	private RedisTemplateUtil redisTemplateUtil;

	class Average{
		private byte sex;
		private int count = 0;
		private double totalScore = 0;
		public double avg() {
			return totalScore / count;
		}
	}
	
	class WeekTime{

		private long gradeId;

		private long classId;

		private int week;
		
		private int times = 0;
	}
	
	class WeekAvgTime{

		private long gradeId;

		private long classId;
		
		private int count = 0;
		
		private double totalTimes = 0;
	}

	@Override
	public BCDTBasicDto getBCDTBasic(Map<String, Object> params) {
		String redisKey = RedisKeyConstant.SPORTS + "getBCDTBasic:"+params.toString();
		BCDTBasicDto dto;
		dto = (BCDTBasicDto)redisTemplateUtil.get(redisKey);
		if (dto != null) return dto;
		dto = statisticsMapper.getBCDTBasic(params);
		BCDTBasicDto dto1 = statisticsMapper.getOrgDataCount(params);
		if (dto != null && dto1 != null){
			dto.setStudentCount(dto1.getStudentCount());
			dto.setTeacherCount(dto1.getTeacherCount());
			dto.setBoyCount(dto1.getBoyCount());
			dto.setGirlCount(dto1.getGirlCount());
			dto.setClassCount(dto1.getClassCount());
			redisTemplateUtil.set(redisKey,dto, 6, TimeUnit.HOURS);
		}
		return dto;
	}

	@Override
	public BCDTDto getBCDT(Map<String, Object> params) {
		String redisKey = RedisKeyConstant.SPORTS + "getBCDT:"+params.toString();
		BCDTDto dto;
		dto = (BCDTDto)redisTemplateUtil.get(redisKey);
		if (dto != null) return dto;
		dto = new BCDTDto();
		dto.setSchoolAttendRateDto(statisticsMapper.getSchoolAttendRate(params));
		dto.setDetectStatisticsDto(statisticsMapper.getDetectStatistics(params));
		dto.setTrainGradeCounts(statisticsMapper.getTrainGradeCounts(params));
		PhysicalAnalysisDto physicalAnalysisDto = trainMapper.getTeacherPhysicalAnalysis(params);
		dto.setPhysicalAnalysisDto(physicalAnalysisDto);
		dto.format();
		redisTemplateUtil.set(redisKey,dto, 6, TimeUnit.HOURS);
		return dto;
	}

	@Override
	public BCDTKindDto getBCDTByKind(Map<String, Object> params) {
		String redisKey = RedisKeyConstant.SPORTS + "getBCDTByKind:"+params.toString();
		BCDTKindDto dto;
		dto = (BCDTKindDto)redisTemplateUtil.get(redisKey);
		if (dto != null) return dto;
		dto = statisticsMapper.getBCDTKindDto(params);
		redisTemplateUtil.set(redisKey,dto, 6, TimeUnit.HOURS);
		return dto;
	}

	@Override
	public BCDTNowKindDto getNowBCDTByKind(Map<String, Object> params) {
		BCDTNowKindDto dto = statisticsMapper.getBCDTNowKindDto(params);
		dto.setTrainDtos(statisticsMapper.getNowTrainList(params));
		return dto;
	}

	@Override
	public List<DistrictDto> getCityListByOrg() {
		return statisticsMapper.getCityListByOrg();
	}


	@Override
	public TrainAnalysisDto getTrainHomePage(Map<String, Object> params) {
		String redisKey = RedisKeyConstant.SPORTS + "getTrainHomePage:"+params.toString();
		TrainAnalysisDto trainAnalysisDto = (TrainAnalysisDto)redisTemplateUtil.get(redisKey);
		if (trainAnalysisDto != null) return trainAnalysisDto;
		trainAnalysisDto = new TrainAnalysisDto();
		//学生人数、教师人数、班级数
		BCDTBasicDto dto = statisticsMapper.getOrgDataCount(params);
		if(null!= dto)
		{
			trainAnalysisDto.setStudentCount(dto.getStudentCount());
			trainAnalysisDto.setClassCount(dto.getClassCount());
			trainAnalysisDto.setTeacherCount(dto.getTeacherCount());
		}
//		ResultDTO<Map<String, Integer>> result = basicFeignService.getOrgDataCount(orgId);
//		Map<String, Integer> resultMap = result.getData();
//		if(result.isSuccess() && null!= resultMap)
//		{
//			trainAnalysisDto.setStudentCount(resultMap.get("studentCount"));
//			trainAnalysisDto.setClassCount(resultMap.get("classCount"));
//			trainAnalysisDto.setTeacherCount(resultMap.get("teacherCount"));
//		}
		//训练时长、训练次数
		TrainAnalysisDto teacherTrainStat = trainMapper.getTeacherTrainStat(params);
		trainAnalysisDto.setTrainTotalTime(teacherTrainStat.getTrainTotalTime());
		trainAnalysisDto.setTrainCount(teacherTrainStat.getTrainCount());

		PhysicalAnalysisDto physicalAnalysisDto = trainMapper.getTeacherPhysicalAnalysis(params);
		trainAnalysisDto.setPhysicalAnalysisDto(physicalAnalysisDto);
		trainAnalysisDto.format();
		redisTemplateUtil.set(redisKey,trainAnalysisDto, 6, TimeUnit.HOURS);
		return trainAnalysisDto;
	}

	@Override
	public TrainAnalysisDto getTrainHomePageKind(Map<String, Object> params) {
		String redisKey = RedisKeyConstant.SPORTS + "getTrainHomePageKind:"+params.toString();
		TrainAnalysisDto trainAnalysisDto = (TrainAnalysisDto)redisTemplateUtil.get(redisKey);
		if (trainAnalysisDto != null) return trainAnalysisDto;
		trainAnalysisDto = new TrainAnalysisDto();
		//学生人数、教师人数、班级数
		TAnalysisDto dto = trainStudentMapper.getPCTrainDistributeStat(params);
		trainAnalysisDto.setTAnalysisDto(dto);

		List<TAnalysisDto> distributeList = trainStudentMapper.getGradeTrainDistributeStat(params);
		trainAnalysisDto.setGradeTrainList(distributeList);
		redisTemplateUtil.set(redisKey,trainAnalysisDto, 6, TimeUnit.HOURS);
		return trainAnalysisDto;
	}

	@Override
	public List<TrainSummaryDto> queryTrainSummaryList(String arrays, Long gradeId) throws Exception {
		return trainStudentMapper.queryTrainSummaryList(arrays, gradeId);
	}
	
	public Map<Long, Double> queryTrainTimeList(String arrays, Level level)throws Exception{
		List<TrainTimeDto> dtos = trainMapper.queryTrainTimeList(arrays);
		Map<String, WeekTime> times = new HashMap<>();
		//计算每周训练次数
		Calendar cal = Calendar.getInstance();
		for(TrainTimeDto dto : dtos) {
			String key = level == Level.org ? dto.getGradeId() + "_" : dto.getClassId() + "_";
			long time = dto.getStartTime().getTime();
			cal.setTimeInMillis(time);
			int weeks = cal.get(Calendar.WEEK_OF_YEAR);
			int year = cal.get(Calendar.YEAR);
			key += year + "_" + weeks;
			WeekTime weekTime = times.get(key);
			if(weekTime == null) {
				weekTime = new WeekTime();
				weekTime.gradeId = dto.getGradeId();
				weekTime.classId = dto.getClassId();
				weekTime.week = weeks;
				times.put(key, weekTime);
			}
			weekTime.times++;
		}
		Map<String, WeekAvgTime> avgTimes = new HashMap<>();
		for(WeekTime weekTime : times.values()) {
			String key = level == Level.org ? weekTime.gradeId + "_" :  weekTime.classId + "_";
			WeekAvgTime weekAvgTime = avgTimes.get(key);
			if(weekAvgTime == null) {
				weekAvgTime = new WeekAvgTime();
				weekAvgTime.gradeId = weekTime.gradeId;
				weekAvgTime.classId = weekTime.classId;
				avgTimes.put(key, weekAvgTime);
			}
			weekAvgTime.count++;
			weekAvgTime.totalTimes += weekTime.times;
		}
		Map<Long, Double> results = new HashMap<>();
		for(WeekAvgTime avgTime : avgTimes.values()) {
			Long key = level == Level.org ? avgTime.gradeId :  avgTime.classId;
			Double value = avgTime.totalTimes / avgTime.count;
			results.put(key, value);
		}
		return results;
	}

	@Override
	public TrainStudentSummaryDto getTrainStudentSummary(String arrays) throws Exception {
		List<HlifeTrainStudent> students = trainStudentMapper.getListByTrans(arrays);
		Map<Long, Average> studentAverages = new HashMap<>();
		for(HlifeTrainStudent student : students) {
			Long studentId = student.getId();
			Average average = studentAverages.get(studentId);
			if(average == null) {
				average = new Average();
				average.sex = student.getSex();
				studentAverages.put(studentId, average);
			}
			average.count++;
			average.totalScore += student.getTotalScore();
		}
		TrainStudentSummaryDto dto = new TrainStudentSummaryDto();
		StatisticsStudent ss = new StatisticsStudent();
		for(Long key : studentAverages.keySet()) {
			Average average = studentAverages.get(key);
			
			ss.calculateLevel(average.sex, average.avg());
		}
		ss.bindStudentSummary(dto);
		return dto;
	}

	/**
	 * 获取所有满足条件的训练ID
	 */
	public String getTrainIds(Map<String, Object> params) throws Exception {
		List<Long> trainIds = trainMapper.queryTrainIdList(params);
		if(trainIds.size() <= 0) {
			return null;
		}
		String arrays = Arrays.toString(trainIds.toArray(new Long[trainIds.size()]));
		arrays = arrays.substring(1, arrays.length() - 1);
		return arrays;
	}

	@Override
	public List<JumpGradeSummaryDto> queryTrainGradeSummaryList(String trianIds) throws Exception {
		List<JumpGradeSummaryDto> list = trainStudentMapper.queryJumpGradeSummaryList(trianIds);
		return list;
	}

	@Override
	public List<JumpClassSummaryDto> queryTrainClassSummaryList(Map<String, Object> params) throws Exception {
		List<JumpClassSummaryDto> list = trainStudentMapper.queryJumpClassSummaryList(params);
		return list;
	}

	@Override
	public PageInfo<JumpTrainSummaryDto> queryTrainSummaryList4PC(Map<String, Object> params, int pageNo, int pageSize) throws Exception {
		Page<JumpTrainSummaryDto> page = PageHelper.startPage(pageNo, pageSize, true);
		List<JumpTrainSummaryDto> list = trainStudentMapper.queryJumpTrainSummaryList(params);
		for(JumpTrainSummaryDto dto : list) {
			Long trainId = dto.getTrainId();
			HlifeTrain hlifeTrain = trainMapper.getByPrimaryKey(trainId);
			dto.setMedianCount((hlifeTrain.getFemaleMedianCount() + hlifeTrain.getMaleMedianCount())/2);
			dto.setClassName(hlifeTrain.getClassName());
			dto.setModelType(hlifeTrain.getModelType());
			dto.setStatus(hlifeTrain.getStatus());
			dto.setStartTime(hlifeTrain.getStartTime());
			dto.setEndTime(hlifeTrain.getEndTime());
			dto.setTeacher(getTeacher(hlifeTrain));
		}
		PageInfo<JumpTrainSummaryDto> pageInfo = new PageInfo<>(list);
		pageInfo.setTotal(page.getTotal());
		return pageInfo;
	}

	@Override
	public JumpTrainSummaryDto getTrain(Map<String, Object> params) throws Exception {
		JumpTrainSummaryDto dto = trainStudentMapper.getJumpTrain4PC(params);
		Long trainId = (Long)params.get("trainId");
		HlifeTrain hlifeTrain = trainMapper.getByPrimaryKey(trainId);
//		dto.setMedianCount((hlifeTrain.getFemaleMedianCount() + hlifeTrain.getMaleMedianCount())/2);
		dto.setMedianCount(hlifeTrain.getMaleMedianCount());
		dto.setClassId(hlifeTrain.getClassId());
		dto.setClassName(hlifeTrain.getClassName());
		
		dto.setStatus(hlifeTrain.getStatus());
		dto.setStartTime(hlifeTrain.getStartTime());
		dto.setEndTime(hlifeTrain.getEndTime());
		
		dto.setModelType(hlifeTrain.getModelType());
		dto.setTeacherId(hlifeTrain.getTeacherId());
		dto.setTeacher(getTeacher(hlifeTrain));
		return dto;
	}

	private String getTeacher(HlifeTrain hlifeTrain) {
		ResultDTO<EmployeeInfoDto> result = basicFeignService.getEmployeeInfo(hlifeTrain.getOrgId(), hlifeTrain.getTeacherId());
		EmployeeInfoDto teacherDto = result.getData();
		if(teacherDto != null) {
			return teacherDto.getName();
		}
		return null;
	}

	@Override
	public ProjectOrgAverageDto getOrgAverage(String trianIds) throws Exception {
		ProjectOrgAverageDto dto = trainStudentMapper.getOrgAverage(trianIds);
		List<HlifeTrainStudent> list = trainStudentMapper.getListByTrans(trianIds);
		double medianCount = Statistics.getMedianCount(list);
		dto.setMedianCount(medianCount);
		return dto;
	}

	@Override
	public List<ProjectAverageDto> queryProjectAverageList(String trianIds) throws Exception {
		return trainMapper.getProjectAverage(trianIds);
	}

	@Override
	public List<StatisticsAvgScoreDto> getAvgScoreTrand(Map<String, Object> params) throws Exception {
		List<StatisticsAvgScoreDto> listAvg = new ArrayList<StatisticsAvgScoreDto>();
		//本市所有学校ID
//		ResultDTO<List<Long>>  resultData  = basicFeignService.getOrgListByCity(Long.valueOf(params.get("orgId").toString()));
//		List<Long> listOrgids = resultData.getData();
		List<Long>  listOrgids = new ArrayList<>();
//		listOrgids.add((long) 1452);
		listOrgids.add((long)params.get("orgId"));
		Calendar ca = Calendar.getInstance();
		List<HlifeTrain> list =trainMapper.getListByMapParams(params);
		String endDate,begDate;
		if (list.isEmpty()){
			endDate = DateUtil.convertDateToString(new Date());
		}else{
			endDate = DateUtil.convertDateToString(list.get(0).getEndTime());
		}
		ca.setTime(DateUtil.convertStringToDate(endDate));
		ca.add(Calendar.MONTH, -3);
		begDate = DateUtil.convertDateToString(ca.getTime());
		
		Map<String,Object> map = new HashMap<>();
		map.put("startDate", begDate);
		map.put("endDate", endDate);
		
		List<String> listDate = WeekUtil.doDateByStatisticsType("week",map);
		
		Map<String,Object> paramdate = new HashMap<String,Object>();
		int i = 1;
		int j=8;
		while(j>0){
			
			String edate = listDate.get(listDate.size()-i);
			String bdate = listDate.get(listDate.size()-(i+1));
			paramdate.put("bdate", bdate);
			paramdate.put("edate", edate);
			paramdate.put("listOrgids", listOrgids);
			paramdate.put("projectKind", params.get("projectKind"));
			paramdate.put("classId", params.get("classId"));
			List<HlifeTrain> list1= trainMapper.getTrainList(paramdate);
			StatisticsAvgScore statisticsAvgScore = new StatisticsAvgScore(list1,listOrgids);
			
			listAvg.add(statisticsAvgScore.calAvgScore(params,j));
			j--;
			i=i+2;
			
		}
		return listAvg;
	}

}
